package com.ozo.cloud.common.file.strategy;

import cn.hutool.core.lang.UUID;
import com.ozo.cloud.common.file.constant.FileStoreTypeEnum;
import com.ozo.cloud.common.file.config.FileStoreProperties;
import com.ozo.cloud.common.file.config.StrategyFactory;
import io.minio.*;
import io.minio.messages.Bucket;
import io.minio.messages.DeleteError;
import io.minio.messages.DeleteObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * minio策略实现
 *
 * @author qiangesoft
 * @date 2024-05-13
 */
@Slf4j
@RequiredArgsConstructor
public class MinioStrategyImpl implements FileStrategy {

    private MinioClient minioClient;

    public MinioStrategyImpl(FileStoreProperties fileStoreProperties) {
        this.minioClient = MinioClient.builder()
                .credentials(fileStoreProperties.getAccessKey(), fileStoreProperties.getSecretKey())
                .endpoint(fileStoreProperties.getEndpoint())
                .build();
    }

    @Override
    public boolean existsCatalog(String catalog) throws Exception {
        BucketExistsArgs args = BucketExistsArgs.builder().bucket(catalog).build();
        return minioClient.bucketExists(args);
    }

    @Override
    public void createCatalog(String catalog) throws Exception {
        if (!this.existsCatalog(catalog)) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(catalog).build());
        }
    }

    @Override
    public List<String> listCatalogs() throws Exception {
        return minioClient.listBuckets().stream().map(Bucket::name).collect(Collectors.toList());
    }

    @Override
    public void removeCatalog(String catalog) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(catalog).build());
    }

    @Override
    public String uploadFile(String catalog, MultipartFile file) throws Exception {
        // 参数校验
        Assert.notNull(catalog, "catalog is not blank");
        Assert.notNull(file, "file is not null");

        // 判断目录是否存在
        this.createCatalog(catalog);

        // 文件名
        String originalFilename = file.getOriginalFilename();
        Assert.notNull(originalFilename, "originalFilename is not null");
        String suffix = originalFilename.substring(originalFilename.lastIndexOf(POINT));
        String fileName = UUID.randomUUID() + suffix;

        // 上传
        minioClient.putObject(PutObjectArgs.builder()
                .bucket(catalog)
                .object(fileName)
                .stream(file.getInputStream(), file.getSize(), -1)
                .contentType(file.getContentType())
                .build());
        return catalog + SLASH + fileName;
    }

    @Override
    public void removeFile(String catalog, String fileName) throws Exception {
        minioClient.removeObject(RemoveObjectArgs.builder().bucket(catalog).object(fileName).build());
    }

    @Override
    public void removeFiles(String catalog, List<String> fileNames) throws Exception {
        List<DeleteObject> deleteObjectList = new ArrayList<>();
        for (String fileName : fileNames) {
            DeleteObject deleteObject = new DeleteObject(fileName);
            deleteObjectList.add(deleteObject);
        }
        Iterable<Result<DeleteError>> results = minioClient.removeObjects(RemoveObjectsArgs.builder().bucket(catalog).objects(deleteObjectList).build());
        for (Result<DeleteError> result : results) {
            DeleteError error = result.get();
            log.error("Error in deleting object " + error.objectName() + "; " + error.message());
        }
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        StrategyFactory.register(FileStoreTypeEnum.MINIO, this);
    }
}